#! /usr/bin/env python
# -*- coding: utf-8 -*-

# *************************************************************
#     Filename @  train.py
#       Author @  Huoty
#  Create date @  2016-07-14 20:31:22
#  Description @  request trains
# *************************************************************

from __future__ import absolute_import, print_function, division

import json
import datetime
from collections import OrderedDict

from .utils import str_to_date, request_resources, convert_int
from .station import station_to_code


class Train(object):
    """车次信息"""

    def __init__(self, **kwargs):
        attrs = self.__filter_needed_data(kwargs)
        self.__dict__.update(attrs)

    def __filter_needed_data(self, data):
        """把需要的数据过滤出来作为对象的属性"""
        needed_attrs = [ \
            # 车次信息
            "train_no",            # 车次编号
            "station_train_code",  # 车次
            "start_station_name",  # 该次列车始发站
            "end_station_name",    # 该次列出终点站
            "from_station_name",   # 出发站
            "to_station_name",     # 到达站
            "start_time",          # 发车时间
            "arrive_time",         # 到站时间
            "day_difference",      # 第几日到达
            "lishi",               # 历时时间
            "canWebBuy",           # 是否可以网络购买车票
            "lishiValue",          # 历时时间的分钟数
            "start_train_date",    # 发车日期
            "sale_time",           # 开始售票时间

            # 坐席信息
            "gr_num",   # 高级软卧
            "rw_num",   # 软卧
            "rz_num",   # 软座
            "tz_num",   # 特等座
            "wz_num",   # 无座
            "yw_num",   # 硬卧
            "yz_num",   # 硬座
            "ze_num",   # 二等座
            "zy_num",   # 一等坐
            "swz_num",  # 商务座
        ]

        return {attr: data.get(attr, None) for attr in needed_attrs}

    def __repr__(self):
        return "Train(station_train_code=%s, start_train_date=%s)" % \
            (self.station_train_code, self.start_train_date)

    def __str__(self):
        return self.__repr__()

    def get_train_info_by_filtered(self, seats=None):
        """返回过滤后的车次信息

        seats: 需要过滤出来的坐席类型，list 或者 tuple

        返回一个 list，并按照如下顺序排列：
            [车次, 出发站, 到站时间, 发车时间, 到站时间, 历时, 第几日到达, 坐席...]

        如果 seats 不为空，则按给定的 seats 顺序放回坐席，否做坐席顺序按按如下信息返回：
            商务 特等 一等 二等 高软 软卧 硬卧 软座 硬座 无座
        """
        necessary_attr = ["station_train_code", "from_station_name", "to_station_name", \
            "start_time", "arrive_time", "lishi", "day_difference"]

        if not seats:
            seats = ["swz_num", "tz_num", "zy_num", "ze_num", "gr_num", "rw_num", "yw_num", \
                "rz_num", "yw_num", "wz_num"]

        attrs = self.__dict__
        return [attrs.get(item, "--") for item in necessary_attr + list(seats)]

    def get_seats_info(self):
        """获取坐席信息"""
        seat_names = ["gr_num", "rw_num", "rz_num", "tz_num", "wz_num", "yw_num", \
            "yz_num", "ze_num", "zy_num", "swz_num"]

        attrs = self.__dict__
        return {sn: convert_int(attrs.get(sn)) for sn in seat_names}

class TrainTicketsQuerier(object):
    """查询火车票

    火车类型(train_types)：
        D  动车
        G  高铁
        K  快速
        T  特快
        Z  直达
    坐席类型(seat_types)：
        gr  高级软卧
        rw  软卧
        rz  软座
        tz  特等座
        wz  无座
        yw  硬卧
        yz  硬座
        ze  二等座
        zy  一等座
        sw  商务座

    示例：
        TrainTicketsQuery("北京"，"上海", "2016-10-01", ["D", "G"], ["sw", "zy"])
        查询 2016年10月1号 从 北京 到 上海 的动车和高铁的商务座与一等座
        调用 query() 方法时执行查询动作并返回结果
    """

    query_url = 'https://kyfw.12306.cn/otn/lcxxcx/query'

    def __init__(self, from_station, to_station, date, train_types=None, seat_types=None):
        self.from_station_code = station_to_code(from_station)
        self.to_station_code = station_to_code(to_station)
        self.query_date = date if isinstance(date, datetime.date) else str_to_date(date)

        if train_types is not None:
            all_train_types = ['D', 'G', 'K', 'T', 'Z']
            self.__train_types = [item for item in train_types if item in all_train_types]
        else:
            self.__train_types = []

        if seat_types is not None:
            all_seat_types = ["gr", "rw", "rz", "tz", "wz", "yw", "yz", "ze", "zy", "sw"]
            self.__seat_types = [item + "_num" if item != "sw" else item + "z_num" \
                for item in seat_types if item in all_seat_types]
        else:
            self.__seat_types = []

    def request_datas(self):
        """查询原始的车次数据"""
        params = OrderedDict()
        params['purpose_codes'] = 'ADULT'
        params['queryDate'] = self.query_date
        params['from_station'] = self.from_station_code
        params['to_station'] = self.to_station_code

        body = request_resources(self.query_url, params=params)
        ret = json.loads(body)
        assert ret["status"], body
        assert int(ret["httpstatus"]) == 200, body

        data = ret.get("data", None)
        assert data["flag"]

        return data.get("datas", None)

    def get_trains(self):
        """获取所有的车次信息"""
        datas = self.request_datas()
        return [Train(**data) for data in datas]

    def query(self):
        """查询车票"""
        trains = self.get_trains()

        if self.__train_types:
            tmp_trains = []
            for train in trains:
                if train.station_train_code[0] in self.__train_types:
                    tmp_trains.append(train)
            trains = tmp_trains

        return [train.get_train_info_by_filtered(self.__seat_types) for train in trains]

    def __repr__(self):
        return "TrainTicketsQuery(from_station=%s, to_station=%s, date=%s)" % \
            (self.from_station_code, self.to_station_code, self.query_date)

    def __str__(self):
        return self.__repr__()


def get_train_timetable(train_no):
    url = "https://www.so.com/s?ie=utf-8&shb=1&src=360sou_newhome&q=" + train_no
    body = request_resources(url)
    from pyquery import PyQuery
    doc = PyQuery(body)
    table = doc("#mohe-train_number table")
    if not table:
        return None
    return [td.text().split() for td in table("tr").items()]


# Script starts from here

if __name__ == "__main__":
    """车次 车站 时间 历时 商务 特等 一等 二等 高软 软卧 硬卧 软座 硬座 无座"""
    pass
